{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.neural_network import MLPClassifier\n",
    "from sklearn.metrics import classification_report,confusion_matrix\n",
    "from sklearn.metrics import roc_curve, auc\n",
    "from sklearn.feature_selection import SelectFromModel\n",
    "from operator import itemgetter, attrgetter\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from keras.datasets import mnist\n",
    "from keras.utils import np_utils\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Activation\n",
    "from keras.optimizers import RMSprop\n",
    "\n",
    "from array import array\n",
    "import keras.backend as K"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def load_data():\n",
    "    df = pd.read_csv(r'b:\\data.txt',sep='\\t',index_col=0,dtype={'uid': str,'o_uid':str,'i_uid':str,'d_uid':str})\n",
    "    df = df.fillna(0)\n",
    "    df = df.drop(['o_uid','i_uid','d_uid'],1)\n",
    "    df['y_i'] = df['ist_amount'] > 0\n",
    "    df['y_d'] = df['overdue_amount'] > 0\n",
    "    df = df.replace({True:1,False:0})\n",
    "    df = df[~df.index.duplicated()]\n",
    "    \n",
    "    return df\n",
    "\n",
    "def split_data(df,per_train):\n",
    "    train = df.sample(int(len(df)*per_train))\n",
    "    test = df[~df.isin(train).all(1)]\n",
    "    return (train,test)\n",
    "    \n",
    "def prepare_data(df,xs,y,balance = False):\n",
    "    \n",
    "    y_lable = 'y_'+ y\n",
    "\n",
    "    if balance:\n",
    "        df1 = df[df[y_lable] == 1]\n",
    "        df0 = df[df[y_lable] == 0]\n",
    "        if(len(df1)<len(df0)):\n",
    "            df0_s = df0.sample(len(df1))\n",
    "            df = df1.append(df0_s)\n",
    "        else:\n",
    "            df1_s = df1.sample(len(df0))\n",
    "            df = df0.append(df1_s)\n",
    "    \n",
    "    features = []\n",
    "    for x in xs:\n",
    "       s = x+'_'\n",
    "       f = list(filter(lambda x:x.startswith(s),df.columns.tolist()))\n",
    "       features += f\n",
    "    \n",
    "    X = df[features]\n",
    "    y = df[y_lable]\n",
    "    return (X,y)\n",
    "    \n",
    "def score(y_test,preds):\n",
    "    print(pd.crosstab(y_test, preds))\n",
    "    print(classification_report(y_test,preds))\n",
    "    \n",
    "    false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, preds)\n",
    "    roc_auc = auc(false_positive_rate, true_positive_rate)\n",
    "    \n",
    "    plt.title('Receiver Operating Characteristic')\n",
    "    plt.plot(false_positive_rate, true_positive_rate, 'b',\n",
    "    label='AUC = %0.2f'% roc_auc)\n",
    "    plt.legend(loc='lower right')\n",
    "    plt.plot([0,1],[0,1],'r--')\n",
    "    plt.xlim([-0.1,1.2])\n",
    "    plt.ylim([-0.1,1.2])\n",
    "    plt.ylabel('True Positive Rate')\n",
    "    plt.xlabel('False Positive Rate')\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def recall(y_true,y_pred):\n",
    "    total = K.sum(y_true)\n",
    "    right = K.sum(y_true*y_pred)\n",
    "    return right/total"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "df = load_data()\n",
    "df.head()\n",
    "\n",
    "#prepare X,y\n",
    "\n",
    "X,y = prepare_data(df,['o','d'],'i',True)\n",
    "X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.25, random_state=0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#preprocess\n",
    "scaler = StandardScaler()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "## Fit only to the training data\n",
    "scaler.fit(X_train)\n",
    "\n",
    "X_train = scaler.transform(X_train)\n",
    "X_test = scaler.transform(X_test)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "model = Sequential([\n",
    "    Dense(32, input_dim=67, kernel_initializer='uniform'),Activation('relu'),\n",
    "    Dense(16, kernel_initializer='uniform'), Activation('relu'),\n",
    "    Dense(8, kernel_initializer='uniform'), Activation('relu'),\n",
    "    Dense(1, kernel_initializer='uniform'), Activation('sigmoid')]\n",
    ")\n",
    "\n",
    "model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc',recall])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training ------------\n"
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "Error when checking input: expected dense_1_input to have shape (None, 77) but got array with shape (59910, 67)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-9-7e8bab625fdc>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Training ------------'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[1;31m# Another way to train the model\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mhistory\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX_train\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my_train\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mepochs\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m10\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbatch_size\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m32\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32md:\\Users\\qiang.qian\\AppData\\Local\\Continuum\\Anaconda3\\lib\\site-packages\\keras\\models.py\u001b[0m in \u001b[0;36mfit\u001b[0;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, **kwargs)\u001b[0m\n\u001b[1;32m    865\u001b[0m                               \u001b[0mclass_weight\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mclass_weight\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m    866\u001b[0m                               \u001b[0msample_weight\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0msample_weight\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 867\u001b[0;31m                               initial_epoch=initial_epoch)\n\u001b[0m\u001b[1;32m    868\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m    869\u001b[0m     def evaluate(self, x, y, batch_size=32, verbose=1,\n",
      "\u001b[0;32md:\\Users\\qiang.qian\\AppData\\Local\\Continuum\\Anaconda3\\lib\\site-packages\\keras\\engine\\training.py\u001b[0m in \u001b[0;36mfit\u001b[0;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, **kwargs)\u001b[0m\n\u001b[1;32m   1520\u001b[0m             \u001b[0mclass_weight\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mclass_weight\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m   1521\u001b[0m             \u001b[0mcheck_batch_axis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1522\u001b[0;31m             batch_size=batch_size)\n\u001b[0m\u001b[1;32m   1523\u001b[0m         \u001b[1;31m# Prepare validation data.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m   1524\u001b[0m         \u001b[0mdo_validation\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;32mFalse\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[0;32md:\\Users\\qiang.qian\\AppData\\Local\\Continuum\\Anaconda3\\lib\\site-packages\\keras\\engine\\training.py\u001b[0m in \u001b[0;36m_standardize_user_data\u001b[0;34m(self, x, y, sample_weight, class_weight, check_batch_axis, batch_size)\u001b[0m\n\u001b[1;32m   1376\u001b[0m                                     \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_feed_input_shapes\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m   1377\u001b[0m                                     \u001b[0mcheck_batch_axis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1378\u001b[0;31m                                     exception_prefix='input')\n\u001b[0m\u001b[1;32m   1379\u001b[0m         y = _standardize_input_data(y, self._feed_output_names,\n\u001b[1;32m   1380\u001b[0m                                     \u001b[0moutput_shapes\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[0;32md:\\Users\\qiang.qian\\AppData\\Local\\Continuum\\Anaconda3\\lib\\site-packages\\keras\\engine\\training.py\u001b[0m in \u001b[0;36m_standardize_input_data\u001b[0;34m(data, names, shapes, check_batch_axis, exception_prefix)\u001b[0m\n\u001b[1;32m    142\u001b[0m                             \u001b[1;34m' to have shape '\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mstr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mshapes\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m+\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m    143\u001b[0m                             \u001b[1;34m' but got array with shape '\u001b[0m \u001b[1;33m+\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 144\u001b[0;31m                             str(array.shape))\n\u001b[0m\u001b[1;32m    145\u001b[0m     \u001b[1;32mreturn\u001b[0m \u001b[0marrays\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m    146\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: Error when checking input: expected dense_1_input to have shape (None, 77) but got array with shape (59910, 67)"
     ]
    }
   ],
   "source": [
    "print('Training ------------')\n",
    "# Another way to train the model\n",
    "history = model.fit(X_train, y_train, epochs=10, batch_size=32)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "plt.plot(history.history['recall'])\n",
    "plt.plot(history.history['acc'])\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "scores = model.evaluate(X_train, y_train)\n",
    "\n",
    "print(\"%s: %.2f%%\" % (model.metrics_names[1], scores[1]*100))\n",
    "\n",
    "print('\\nTesting ------------')\n",
    "# Evaluate the model with the metrics we defined earlier\n",
    "loss, accuracy, rr = model.evaluate(X_test, y_test)\n",
    "preds = model.predict(X_test)\n",
    "p = []\n",
    "\n",
    "for a in preds:\n",
    "    p.append(int(round(a[0])))\n",
    "\n",
    "confusion_matrix(y_test,p)\n",
    "\n",
    "\n",
    "score(y_test,np.array(p))\n",
    "\n",
    "print('test loss: ', loss)\n",
    "print('test accuracy: ', accuracy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
